import gugga.collections.IIterator;
import gugga.collections.ObjectHashTable;
import gugga.utils.HashUtil;

import test_framework.test.unit.TestCase;

/**
 * @author stefan
 */
class guggaLibTests.ObjectHashTableTest 
		extends TestCase
{
	function ObjectHashTableTest(Void) 
	{
		super();
	}
	
	function testIterationWithForIn ()
	{
		var table : ObjectHashTable = new ObjectHashTable();
		
		table.add({ name: "objectA" }, { name: "object1" } );
		table.add({ name: "objectB" }, { name: "object2" } );
		table.add({ name: "objectC" }, { name: "object3" } );
		
		assertEquals(
			"",
			3,
			table.count
		);
	}
	
	function testComplex ()
	{
		var table : ObjectHashTable = new ObjectHashTable();
		
		var objA : Object = new Object ();
		var objB : Object = new Object ();
		var objC : Object = new Object ();
		
		var obj1 : Object = new Object ();
		var obj2 : Object = new Object ();
		var obj3 : Object = new Object ();
		
		var obj0 : Object = new Object ();
		var objZ : Object = new Object ();
		
		table.add(obj1, objA);
		table.add(obj2, objB);
		table.add(obj3, objC);
		
		assertTrue(
			"table should contains key obj1",
			table.containsKey(obj1)
		);
		
		assertFalse(
			"table should not contains key obj0",
			table.containsKey(obj0)
		);
		
		assertEquals(
			"table.count returns unexpected result: " + table.count + ", should be 3",
			3,
			table.count
		);
		
		assertTrue(
			"table should contains objA",
			table.containsValue(objA)
		);
		
		assertFalse(
			"table should not contains objZ",
			table.containsValue(objZ)
		);
		
		table.remove(obj2);
		
		assertFalse(
			"table should not contains objB after remove",
			table.containsValue(objB)
		);
		
		assertEquals(
			"getKeyByValue returns unexpected results",
			HashUtil.hash(obj3),
			table.getKeyByValue(objC)
		);
		
		var table2 : ObjectHashTable = ObjectHashTable(table.clone());
		
		assertEquals(
			"table.count returns unexpected result: " + table.count + ", should be 3",
			2,
			table2.count
		);
		
		assertEquals(
			"getValue unexpected result",
			objC,
			table2.getValue(obj3)
		);
		
	}
	
	function testObjectTypesVariation () : Void
	{
		var table : ObjectHashTable = new ObjectHashTable();
		
		var objA : String = "objA";
		var objB : Number = 766;
		var objC : Object = new Object ();
		
		var obj1 : Object = new Object ();
		var obj2 : Object = new Object ();
		var obj3 : Object = new Object ();
		
		var obj0 : Object = new Object ();
		var objZ : Object = new Object ();
		
		table.add(obj1, objA);
		table.add(obj2, objB);
		table.add(obj3, objC);
		
		assertTrue(
			"table should contains key obj1",
			table.containsKey(obj1)
		);
		
		assertTrue(
			"table should contains key obj1",
			table.containsKey(obj2)
		);
		
		assertTrue(
			"table should contains key obj1",
			table.containsKey(obj3)
		);
		
		assertTrue(
			"table should contains objA",
			table.containsValue(objA)
		);
		
		assertTrue(
			"table should contains objB",
			table.containsValue(objB)
		);
		
		assertTrue(
			"table should contains objC",
			table.containsValue(objC)
		);
		
		assertFalse(
			"table should not contains key obj0",
			table.containsKey(obj0)
		);
		
		assertEquals(
			"table.count returns unexpected result: " + table.count + ", should be 3",
			3,
			table.count
		);
		
		assertTrue(
			"table should contains objA",
			table.containsValue(objA)
		);
		
		assertFalse(
			"table should not contains objZ",
			table.containsValue(objZ)
		);
		
		table.remove(obj2);
		
		assertFalse(
			"table should not contains objB after remove",
			table.containsValue(objB)
		);
		
		assertEquals(
			"getKeyByValue returns unexpected results",
			HashUtil.hash(obj3),
			table.getKeyByValue(objC)
		);
		
		var table2 : ObjectHashTable = ObjectHashTable(table.clone());
		
		assertEquals(
			"table.count returns unexpected result: " + table.count + ", should be 3",
			2,
			table2.count
		);
		
		assertEquals(
			"getValue unexpected result",
			objC,
			table2.getValue(obj3)
		);
	}
	
	function testGetIterator ()
	{
		var table : ObjectHashTable = new ObjectHashTable();
		
		var objA : Object = new Object ();
		var objB : Object = new Object ();
		var objC : Object = new Object ();
		
		var obj1 : Object = new Object ();
		var obj2 : Object = new Object ();
		var obj3 : Object = new Object ();
		
		table.add(objA, obj1);
		table.add(objB, obj2);
		table.add(objC, obj3);
		
		var iterator : IIterator = table.getIterator();
		assertThrowsWithFunctionAndMessage(
			"iterator.current() should raise an exception after creation - " +
			"collection[-1] is out of bounds exception", 
			iterator, 
			iterator.current, 
			null
		);
		
		iterator.iterate();
		assertEquals(
			"iterator.current() should be equal to obj1",
			obj1,
			iterator.current()
		);
		
		iterator.iterate();
		assertEquals(
			"iterator.current() should be equal to obj2",
			obj2,
			iterator.current()
		);

		iterator.iterate();
		assertEquals(
			"iterator.current() should be equal to obj3",
			obj3,
			iterator.current()
		);
		
		assertFalse(
			"iterate() should be false when the cursor reachs end of list",
			iterator.iterate()
		);
		
		iterator.reset();
		assertThrowsWithFunctionAndMessage(
			"iterator.current() should raise an exception after reset - " +
			"collection[-1] is out of bounds exception", 
			iterator, 
			iterator.current, 
			null
		);
	}
}